package hdgeom.primitives;



import processing.core.PGraphics;
import processing.core.PMatrix3D;
import processing.core.PVector;

public abstract class AbstractFace extends AbstractShape {

	public void display3D(PGraphics g) {
		float[] coords = new float[3];
		int nNodes = getNumVertices();
		if (nNodes == 4) {
			g.beginShape(PGraphics.QUADS);
			for (int i = 0; i < nNodes; i++) {
				getPosition(i, coords);
				g.vertex(coords[0], coords[1], coords[2]);
			}
			g.endShape();
		} else if (nNodes == 3) {
			g.beginShape(PGraphics.TRIANGLES);
			for (int i = 0; i < nNodes; i++) {
				getPosition(i, coords);
				g.vertex(coords[0], coords[1], coords[2]);
			}
			g.endShape();
		} else {
			g.beginShape();
			for (int i = 0; i < nNodes; i++) {
				getPosition(i, coords);
				g.vertex(coords[0], coords[1], coords[2]);
			}
			g.endShape(PGraphics.CLOSE);
		}
	}

	public void display2D(PGraphics g) {
		float[] coords = new float[3];
		int nNodes = getNumVertices();
		if (nNodes == 4) {
			g.beginShape(PGraphics.QUADS);
			for (int i = 0; i < nNodes; i++) {
				getPosition(i, coords);
				g.vertex(coords[0], coords[1]);
			}
			g.endShape();
		} else if (nNodes == 3) {
			g.beginShape(PGraphics.TRIANGLES);
			for (int i = 0; i < nNodes; i++) {
				getPosition(i, coords);
				g.vertex(coords[0], coords[1]);
			}
			g.endShape();
		} else {
			g.beginShape();
			for (int i = 0; i < nNodes; i++) {
				getPosition(i, coords);
				g.vertex(coords[0], coords[1]);
			}
			g.endShape(PGraphics.CLOSE);
		}
	}

	public float getPerimeter() {
		float sum = 0;
		float[] cds1 = new float[3];
		float[] cds2 = new float[3];
		for (int i = 0; i < getNumVertices(); i++) {
			getPosition(i, cds1);
			getPosition((i + 1) % getNumVertices(), cds2);
			sum += distance(cds1, cds2);
		}
		return sum;
	}

	public PVector getNormal() {
		PVector normal = new PVector();
		float[] v1 = new float[3];
		float[] v2 = new float[3];
		float[] v3 = new float[3];
		PVector p1 = new PVector();
		PVector p2 = new PVector();
		PVector p3 = new PVector();
		int nV = this.getNumVertices();
		for (int i = 0; i < nV; i++) {
			getPosition(i, v1);
			getPosition((i + 1) % nV, v2);
			getPosition((i + 2) % nV, v3);
			p1.set(v1[0], v1[1], v1[2]);
			p2.set(v2[0], v2[1], v2[2]);
			p3.set(v3[0], v3[1], v3[2]);
			normal.add(AbstractShape.normal(p1, p2, p3));
		}
		normal.normalize();
		return normal;
	}

	public PMatrix3D getMatrixXY() {
		PMatrix3D rot = new PMatrix3D();
		float[] v1 = new float[3];
		getPosition(0, v1);
		rot.translate(-v1[0], -v1[1], -v1[2]);
		PVector s = new PVector(0, 0, 1); // is already normalized (meaning is
											// has length 1)
		PVector normal = getNormal();
		PVector r = s.cross(normal);
		float a = (float) Math.acos(s.dot(normal));
		rot.rotate(-a, r.x, r.y, r.z);
		return rot;
	}

}
